#include "fxcc/core/graph/directX11/ImGuiWin32App.h"

using namespace fxcc::imgui::graph::directX11;

extern IMGUI_IMPL_API LRESULT ImGui_ImplWin32_WndProcHandler(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam);

fxcc::imgui::graph::directX11::Win32App::Win32App(const Desc& desc)
    :fxcc::graph::directX11::Win32App(desc)
{

}


LRESULT __stdcall fxcc::imgui::graph::directX11::Win32App::OnWndProj(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
    if (ImGui_ImplWin32_WndProcHandler(hWnd, msg, wParam, lParam))
        return true;

    return fxcc::graph::directX11::Win32App::OnWndProj(hWnd, msg, wParam, lParam);
}


void Win32App::OnEdit() {

};

int Win32App::Run()
{
    if (!Init())
    {
        ztclog::info("failed init app");
        return 1;
    }
    bool done = false;
    while (!done)
    {
        MSG msg;
        while (::PeekMessage(&msg, nullptr, 0U, 0U, PM_REMOVE))
        {
            ::TranslateMessage(&msg);
            ::DispatchMessage(&msg);

            if (msg.message == WM_QUIT)
                done = true;
        }


        OnFrameRender();

        // Start the Dear ImGui frame
        ImGui_ImplDX11_NewFrame();
        ImGui_ImplWin32_NewFrame();
        ImGui::NewFrame();

        OnEdit();
        // Rendering
        ImGui::Render();
        ImGui_ImplDX11_RenderDrawData(ImGui::GetDrawData());

        ImGuiIO& io = ImGui::GetIO();
        // Update and Render additional Platform Windows
        if (io.ConfigFlags & ImGuiConfigFlags_ViewportsEnable)
        {
            ImGui::UpdatePlatformWindows();
            ImGui::RenderPlatformWindowsDefault();
        }


        OnUpdate();

        m_Input.Clear();

        if (done)
            break;

        g_pSwapChain->Present(m_Desc.m_Interval, 0);

    }

    OnDestory();

    return 0;
}

bool Win32App::Init()
{
    if (!fxcc::graph::directX11::Win32App::Init())
    {
        return false;
    }
    if (!InitImGui())
    {
        ztclog::info("failed init imgui");
        return false;
    }
    return true;
};

bool fxcc::imgui::graph::directX11::Win32App::InitImGui()
{
    // Setup Dear ImGui context
    IMGUI_CHECKVERSION();
    ImGui::CreateContext();
    ImGuiIO &io = ImGui::GetIO();
    (void)io;
    io.ConfigFlags |= ImGuiConfigFlags_NavEnableKeyboard; // Enable Keyboard Controls
    io.ConfigFlags |= ImGuiConfigFlags_NavEnableGamepad;  // Enable Gamepad Controls
    io.ConfigFlags |= ImGuiConfigFlags_DockingEnable;     // Enable Docking
    // io.ConfigFlags |= ImGuiConfigFlags_ViewportsEnable;   // Enable Multi-Viewport / Platform Windows
    // io.ConfigViewportsNoAutoMerge = true;
    // io.ConfigViewportsNoTaskBarIcon = true;

    // Setup Dear ImGui style
    // ImGui::StyleColorsDark();
    // ImGui::StyleColorsLight();
    ImGui::StyleColorsClassic();

    // When viewports are enabled we tweak WindowRounding/WindowBg so platform windows can look identical to regular ones.
    ImGuiStyle &style = ImGui::GetStyle();
    if (io.ConfigFlags & ImGuiConfigFlags_ViewportsEnable)
    {
        style.WindowRounding = 0.0f;
        style.Colors[ImGuiCol_WindowBg].w = 1.0f;
    }

    // Setup Platform/Renderer backends
    ImGui_ImplWin32_Init(m_hWnd);
    ImGui_ImplDX11_Init(g_pd3dDevice.Get(), g_pImmediateContext.Get());

    ImNodes::CreateContext();

    return true;
}

void Win32App::OnDestory() {

    ImNodes::DestroyContext();

    ImGui_ImplDX11_Shutdown();
    ImGui_ImplWin32_Shutdown();
    ImGui::DestroyContext();

    fxcc::graph::directX11::Win32App::OnDestroy();
};